﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Data.Objects;
using TaskManagement.ModelLayer;

namespace DataAccess
{

    public class DBTask : IDBTask
    {
        private TaskContext context;

        public DBTask()
        {
            context = new TaskContext();
            context.Configuration.LazyLoadingEnabled = false;
        }


        public IList<Task> SearchTask(Task searchTask)
        {
            IList<Task> results = null;
            try
            {
                var query = from task in context.TaskEntitySet.Include("EmployeeEntity").Include("WorkflowEntity")
                            .Include("AccountEntity").Include("TagEntity").Include("DeliveryEntity")
                            select task;

                if (!String.IsNullOrWhiteSpace(searchTask.Account))
                    query = query.Where(task => task.AccountEntity.Account.Equals(searchTask.Account));

                if (searchTask.Employee != null)
                    query = query.Where(task => task.EmployeeEntity.Id == searchTask.Employee.Id);

                if (searchTask.Date != null)
                    query = query.Where(task => task.Date == searchTask.Date);

                if (searchTask.Id != 0)
                    query = query.Where(task => task.Id == searchTask.Id);

                if (!String.IsNullOrWhiteSpace(searchTask.Description))
                    query = query.Where(task => task.Description.Equals(searchTask.Description));

                if (!String.IsNullOrWhiteSpace(searchTask.Delivery))
                    query = query.Where(task => task.DeliveryEntity.Delivery.Equals(searchTask.Delivery));

                if (searchTask.Estiamte != -1)
                    query = query.Where(task => task.Estimate == searchTask.Estiamte);

                if (!String.IsNullOrWhiteSpace(searchTask.Status))
                    query = query.Where(task => task.Status.Equals(searchTask.Status));

                if (!String.IsNullOrWhiteSpace(searchTask.Tag))
                    query = query.Where(task => task.TagEntity.Tag.Equals(searchTask.Tag));

                if (searchTask.TimeSpent != -1)
                    query = query.Where(task => task.TimeSpent == searchTask.TimeSpent);

                results = Converter.ConvertTasktList(query.ToList(), true, true, true, true);
            }
            catch (Exception e)
            {
                ErrorLog.LogEvent("TaskManagement", "TaskManagement log", e.Message, 102, EventLogEntryType.Error);
            }

            return results;
        }

        public int CreateTask(Task task)
        {
            int ret = 0;
            try
            {
                TaskEntity te = Converter.ConvertTaskEntity(task, false);
                te.TagEntity = GetTagEntityByTag(task.Tag);
                te.DeliveryEntity = GetDeliveryEntityByDelivery(task.Delivery);
                te.AccountEntity = GetAccountEntityByAccount(task.Account);

                context.TaskEntitySet.Add(te);
                context.SaveChanges();
                ret += te.Id;
            }
            catch (Exception e)
            {
                ErrorLog.LogEvent("TaskManagement", "TaskManagement log", e.Message, 99, EventLogEntryType.Error);
            }

            return ret;
        }

        public int DeleteTasks(IList<Task> tasks)
        {
            int ret = 0;
            try
            {
                foreach (Task task in tasks)
                {
                    TaskEntity te = Converter.ConvertTaskEntity(task, false);
                    context.TaskEntitySet.Attach(te);
                    context.TaskEntitySet.Remove(te);
                }

                context.SaveChanges();
                ret += 1;
            }
            catch (Exception e)
            {
                ErrorLog.LogEvent("TaskManagement", "TaskManagement log", e.Message, 100, EventLogEntryType.Error);
            }

            return ret;
        }


        public int UpdateTasks(Task task)
        {
            int ret = 0;
            try
            {
                TaskEntity te = Converter.ConvertTaskEntity(task, false);
                te.AccountEntity = GetAccountEntityByAccount(task.Account);
                te.DeliveryEntity = GetDeliveryEntityByDelivery(task.Delivery);
                te.TagEntity = GetTagEntityByTag(task.Tag);
                context.TaskEntitySet.Attach(te);
                context.Entry(te).State = System.Data.EntityState.Modified;
                context.SaveChanges();
                ret = 1;
            }
            catch (Exception e)
            {
                ErrorLog.LogEvent("TaskManagement", "TaskManagement log", e.Message, 101, EventLogEntryType.Error);
            }

            return ret;

        }

        public IList<string> GetAccounts()
        {
            List<string> list = null;
            try
            {
                var query = from a in context.AccountEntitySet orderby a.Account select a.Account;
                list = query.ToList();
            }
            catch (Exception e)
            {
                ErrorLog.LogEvent("TaskManagement", "TaskManagement log", e.Message, 103, EventLogEntryType.Error);

            }

            return list;
        }

        public IList<string> GetDeliverys()
        {
            List<string> list = null;
            try
            {
                var query = from d in context.DeliveryEntitySet orderby d.Delivery select d.Delivery;
                list = query.ToList();
            }
            catch (Exception e)
            {
                ErrorLog.LogEvent("TaskManagement", "TaskManagement log", e.Message, 104, EventLogEntryType.Error);
            }

            return list;
        }

        public IList<string> GetTags()
        {

            List<string> list = null;
            try
            {
                var query = from t in context.TagEntitySet orderby t.Tag select t.Tag;
                list = query.ToList();
            }
            catch (Exception e)
            {
                ErrorLog.LogEvent("TaskManagement", "TaskManagement log", e.Message, 105, EventLogEntryType.Error);
            }

            return list;
        }

        /// <summary>
        /// Gets the tagEntity with the given tag from the db
        /// If it doesnt excist it creates it and returns the newly created entity
        /// </summary>
        /// <param name="tag">The tag</param>
        /// <returns>The TagEntity with the given tag</returns>
        private TagEntity GetTagEntityByTag(string tag)
        {
            var query = from t in context.TagEntitySet where t.Tag == tag select t;
            TagEntity te = query.FirstOrDefault();
            if (te == null)
            {
                te = new TagEntity();
                te.Tag = tag;
                context.TagEntitySet.Add(te);
                context.SaveChanges();
            }

            return te;
        }

        /// <summary>
        /// Gets the AccountEntity with the given account from the db
        /// If it doesnt excist it creates it and returns the newly created entity
        /// </summary>
        /// <param name="account">The account</param>
        /// <returns>The AccountEntity with the given account</returns>
        private AccountEntity GetAccountEntityByAccount(string account)
        {
            var query = from a in context.AccountEntitySet where a.Account == account select a;
            AccountEntity ae = query.FirstOrDefault();
            if (ae == null)
            {
                ae = new AccountEntity();
                ae.Account = account;
                context.AccountEntitySet.Add(ae);
                context.SaveChanges();
            }

            return ae;
        }

        private DeliveryEntity GetDeliveryEntityByDelivery(string delivery)
        {
            var query = from d in context.DeliveryEntitySet where d.Delivery == delivery select d;
            DeliveryEntity de = query.FirstOrDefault();
            if (de == null)
            {
                de = new DeliveryEntity();
                de.Delivery = delivery;
                context.DeliveryEntitySet.Add(de);
                context.SaveChanges();
            }

            return de;
        }


    }
}
